﻿using DotNetExtensions.AspNet.DevExpress.WIN;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Printing;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;

namespace DevExpressSimple
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            this.Moveable();
            this.AddMoveable(new Control[] { this.panel1 });

            SvgCollection.Default.From(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Resources"));
            this.iconButton1.Image = SvgCollection.Default.TryGet("Close");
            this.iconButton2.Image = SvgCollection.Default.TryGet("Maximizing");
            this.iconButton3.Image = SvgCollection.Default.TryGet("Hide");

            this.Load += (sender, e) =>
            {
                dwmInitialize();
            };
        }
        public void DrawRoundRectangle(Graphics g, Pen pen, Rectangle rect, int cornerRadius)
        {
            using (GraphicsPath path = CreateRoundedRectanglePath(rect, cornerRadius))
            {
                g.DrawPath(pen, path);
            }
        }
        public void FillRoundRectangle(Graphics g, Brush brush, Rectangle rect, int cornerRadius)
        {
            using (GraphicsPath path = CreateRoundedRectanglePath(rect, cornerRadius))
            {
                g.FillPath(brush, path);
            }
        }
        internal GraphicsPath CreateRoundedRectanglePath(Rectangle rect, int cornerRadius)
        {
            GraphicsPath roundedRect = new GraphicsPath();
            roundedRect.AddArc(rect.X, rect.Y, cornerRadius * 2, cornerRadius * 2, 180, 90);
            roundedRect.AddLine(rect.X + cornerRadius, rect.Y, rect.Right - cornerRadius * 2, rect.Y);
            roundedRect.AddArc(rect.X + rect.Width - cornerRadius * 2, rect.Y, cornerRadius * 2, cornerRadius * 2, 270, 90);
            roundedRect.AddLine(rect.Right, rect.Y + cornerRadius * 2, rect.Right, rect.Y + rect.Height - cornerRadius * 2);
            roundedRect.AddArc(rect.X + rect.Width - cornerRadius * 2, rect.Y + rect.Height - cornerRadius * 2, cornerRadius * 2, cornerRadius * 2, 0, 90);
            roundedRect.AddLine(rect.Right - cornerRadius * 2, rect.Bottom, rect.X + cornerRadius * 2, rect.Bottom);
            roundedRect.AddArc(rect.X, rect.Bottom - cornerRadius * 2, cornerRadius * 2, cornerRadius * 2, 90, 90);
            roundedRect.AddLine(rect.X, rect.Bottom - cornerRadius * 2, rect.X, rect.Y + cornerRadius * 2);
            roundedRect.CloseFigure();
            return roundedRect;
        }
        protected override CreateParams CreateParams
        {
            get
            {
                CreateParams cp = base.CreateParams;
                cp.Style = cp.Style | WS_MINIMIZEBOX;
                return cp;
            }
        }
        protected override void OnPaint(PaintEventArgs e)
        {
            base.OnPaint(e);
            e.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
            if (dwmEnabled)
            {
                e.Graphics.Clear(Color.FromArgb(0, 0, 0, 0));
                DrawShadow(this.Size, dwmleft, e.Graphics);
            }
            RectangleF rect = new RectangleF(dwmleft - 0.5f, dwmtop - 0.5f, this.Width - dwmleft - dwmright + 0.5f, this.Height - dwmtop - dwmbottom + 0.5f);
            SolidBrush brush = new SolidBrush(this.BackColor);
            e.Graphics.FillRectangle(brush, rect);
            brush.Dispose(); brush = null;

        }
        void Shadow()
        {
            Bitmap bitmap = null;
            Graphics g = null;
            try
            {
                bitmap = new Bitmap(Width, Height);
                g = Graphics.FromImage(bitmap);
                g.SmoothingMode = SmoothingMode.AntiAlias;

                Color c = Color.Red;
                Pen p = new Pen(c, 3);

                for (int i = 0; i < 10; i++)
                {
                    p.Color = Color.FromArgb((255 / 10 / 10) * i, c);
                    DrawRoundRectangle(g, p, new Rectangle(i, i, Width - (2 * i) - 1, Height - (2 * i) - 1), 10 - i);
                }
                g.Flush();
                Render(bitmap);
            }
            catch { }
            finally
            {
                g?.Dispose();
                bitmap?.Dispose();
            }
        }
        private void Render(Bitmap bitmap)
        {
            if (!Image.IsCanonicalPixelFormat(bitmap.PixelFormat) || !Image.IsAlphaPixelFormat(bitmap.PixelFormat)) throw new Exception();
            IntPtr oldBits = IntPtr.Zero;
            IntPtr screenDC = Win32.GetDC(IntPtr.Zero);
            IntPtr hBitmap = IntPtr.Zero;
            IntPtr memDc = Win32.CreateCompatibleDC(screenDC);

            try
            {
                POINT topLoc = new POINT(Left, Top);
                SIZE bitMapSize = new SIZE(Width, Height);
                BLENDFUNCTION blendFunc = new BLENDFUNCTION();
                POINT srcLoc = new POINT(0, 0);

                hBitmap = bitmap.GetHbitmap(Color.FromArgb(0));
                oldBits = Win32.SelectObject(memDc, hBitmap);

                blendFunc.BlendOp = 0x00;
                blendFunc.SourceConstantAlpha = byte.MaxValue;
                blendFunc.AlphaFormat = 0x01;
                blendFunc.BlendFlags = 0;

                Win32.UpdateLayeredWindow(Handle, screenDC, ref topLoc, ref bitMapSize, memDc, ref srcLoc, 0, ref blendFunc, 0x02);
            }
            finally
            {
                if (hBitmap != IntPtr.Zero)
                {
                    Win32.SelectObject(memDc, oldBits);
                    Win32.DeleteObject(hBitmap);
                }
                Win32.ReleaseDC(IntPtr.Zero, screenDC);
                Win32.DeleteDC(memDc);
            }
        }
        protected override void WndProc(ref Message m)
        {
            base.WndProc(ref m);
            this.WndResize(ref m, 10);
        }

        private void panel1_MouseClick(object sender, MouseEventArgs e)
        {
            Console.WriteLine("Exec Mouse Click");
        }

        private void iconButton2_Click(object sender, EventArgs e)
        {
            if (WindowState == FormWindowState.Maximized)
            {
                WindowState = FormWindowState.Normal;
                this.iconButton2.Image = SvgCollection.Default.TryGet("Maximizing");

            }
            else
            {
                WindowState = FormWindowState.Maximized;
                this.iconButton2.Image = SvgCollection.Default.TryGet("Minimizing");

            }
        }

        private void iconButton1_Click(object sender, EventArgs e)
        {
            Close();
        }

        private void iconButton3_Click(object sender, EventArgs e)
        {
            WindowState = FormWindowState.Minimized;
        }

        /// <summary>
        /// 绘制阴影效果
        /// </summary>
        /// <param name="size">控件尺寸</param>
        /// <param name="radius">阴影半径</param>
        /// <param name="g">绘图区</param>
        private void DrawShadow(Size size, int radius, Graphics g)
        {
            if (radius <= 0) return;
            int d = 2 * radius;
            #region[LinearGradientBrush]   
            ColorBlend blend = new ColorBlend();
            blend.Colors = new Color[] { Color.FromArgb(100, Color.Black), Color.FromArgb(40, Color.Black), Color.FromArgb(0, Color.Black) };
            blend.Positions = new float[] { 0, 0.4f, 1 };
            LinearGradientBrush brushleft = new LinearGradientBrush(new Point(radius, 0), new Point(0, 0), Color.FromArgb(60, Color.Black), Color.FromArgb(0, Color.Black));
            brushleft.InterpolationColors = blend;
            LinearGradientBrush brushright = new LinearGradientBrush(new Point(size.Width - radius - 1, 0), new Point(size.Width, 0), Color.FromArgb(80, Color.Black), Color.FromArgb(0, Color.Black));
            brushright.InterpolationColors = blend;
            LinearGradientBrush brushtop = new LinearGradientBrush(new Point(0, radius), new Point(0, 0), Color.FromArgb(60, Color.Black), Color.FromArgb(0, Color.Black));
            brushtop.InterpolationColors = blend;
            LinearGradientBrush brushbottom = new LinearGradientBrush(new Point(0, size.Height - radius - 1), new Point(0, size.Height), Color.FromArgb(80, Color.Black), Color.FromArgb(0, Color.Black));
            brushbottom.InterpolationColors = blend;
            #endregion
            #region[path]
            GraphicsPath pathlefttop = new GraphicsPath();
            pathlefttop.AddPie(new Rectangle(0, 0, d, d), 180, 90);
            GraphicsPath pathrighttop = new GraphicsPath();
            pathrighttop.AddPie(new Rectangle(this.Width - d, 0, d, d), 270, 90);
            GraphicsPath pathleftbottom = new GraphicsPath();
            pathleftbottom.AddPie(new Rectangle(0, this.Height - d, d, d), 90, 90);
            GraphicsPath pathrightbottom = new GraphicsPath();
            pathrightbottom.AddPie(new Rectangle(this.Width - d, this.Height - d, d, d), 0, 90);
            #endregion
            #region[PathGradientBrush]
            PathGradientBrush brushlefttop = new PathGradientBrush(pathlefttop);
            brushlefttop.CenterPoint = new Point(radius, radius);
            brushlefttop.CenterColor = Color.FromArgb(80, Color.Black);
            brushlefttop.SurroundColors = new Color[] { Color.FromArgb(0, Color.Black) };
            //brushlefttop.InterpolationColors = blend;
            PathGradientBrush brushrighttop = new PathGradientBrush(pathrighttop);
            brushrighttop.CenterPoint = new Point(this.Width - radius, radius);
            brushrighttop.CenterColor = Color.FromArgb(80, Color.Black);
            brushrighttop.SurroundColors = new Color[] { Color.FromArgb(0, Color.Black) };
            //brushrighttop.InterpolationColors = blend;
            PathGradientBrush brushleftbottom = new PathGradientBrush(pathleftbottom);
            brushleftbottom.CenterPoint = new Point(radius, this.Height - radius);
            brushleftbottom.CenterColor = Color.FromArgb(80, Color.Black);
            brushleftbottom.SurroundColors = new Color[] { Color.FromArgb(0, Color.Black) };
            //brushleftbottom.InterpolationColors = blend;
            PathGradientBrush brushrightbottom = new PathGradientBrush(pathrightbottom);
            brushrightbottom.CenterPoint = new Point(this.Width - radius, this.Height - radius);
            brushrightbottom.CenterColor = Color.FromArgb(80, Color.Black);
            brushrightbottom.SurroundColors = new Color[] { Color.FromArgb(0, Color.Black) };
            //brushrightbottom.InterpolationColors = blend;
            #endregion
            #region[draw]
            g.FillRectangle(brushleft, new RectangleF(1, radius - 0.5f, radius, this.Height - d + 0.5f));
            g.FillRectangle(brushright, new RectangleF(this.Width - radius - 1, radius - 0.5f, radius, this.Height - d + 0.5f));
            g.FillRectangle(brushtop, new RectangleF(radius - 0.5f, 0, this.Width - d + 0.5f, radius));
            g.FillRectangle(brushbottom, new RectangleF(radius - 0.5f, this.Height - radius - 1, this.Width - d + 0.5f, radius));
            g.FillPath(brushlefttop, pathlefttop);
            g.FillPath(brushrighttop, pathrighttop);
            g.FillPath(brushleftbottom, pathleftbottom);
            g.FillPath(brushrightbottom, pathrightbottom);
            #endregion
            #region[dispose]
            brushleft.Dispose(); brushleft = null;
            brushright.Dispose(); brushright = null;
            brushtop.Dispose(); brushtop = null;
            brushbottom.Dispose(); brushbottom = null;
            pathlefttop.Dispose(); pathlefttop = null;
            pathrighttop.Dispose(); pathrighttop = null;
            pathleftbottom.Dispose(); pathleftbottom = null;
            pathrightbottom.Dispose(); pathrightbottom = null;
            brushlefttop.Dispose(); brushlefttop = null;
            brushrighttop.Dispose(); brushrighttop = null;
            brushleftbottom.Dispose(); brushleftbottom = null;
            brushrightbottom.Dispose(); brushrightbottom = null;
            #endregion
        }
        /// <summary>
        /// 初始化
        /// </summary>
        private void Initialize()
        {
            this.SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer, true);
            this.FormBorderStyle = FormBorderStyle.None;
            this.StartPosition = FormStartPosition.CenterScreen;


        }

        protected bool dwmEnabled;
        protected int dwmleft;
        protected int dwmtop;
        protected int dwmright;
        protected int dwmbottom;
        private const int WS_MINIMIZEBOX = 0x00020000;
        /// <summary>
        /// 
        /// </summary>
        public struct MARGINS
        {
            public int m_Left;
            public int m_Right;
            public int m_Top;
            public int m_Bottom;
        };
        [DllImport("dwmapi.dll")]
        private static extern void DwmIsCompositionEnabled(ref int enabledptr);
        [DllImport("dwmapi.dll", PreserveSig = false)]
        public static extern bool DwmIsCompositionEnabled();
        [DllImport("dwmapi.dll")]
        private static extern void DwmExtendFrameIntoClientArea(IntPtr hWnd, ref MARGINS margin);
        /// <summary>
        /// dwm初始化
        /// </summary>
        private void dwmInitialize()
        {
            #region[dwmInitialize]
            this.dwmEnabled = true;
            dwmleft = this.Padding.Left;
            dwmtop = this.Padding.Top;
            dwmright = this.Padding.Right;
            dwmbottom = this.Padding.Bottom;
            int flag = 0;
            MARGINS mg = new MARGINS();
            mg.m_Left = dwmleft;
            mg.m_Top = dwmtop;
            mg.m_Right = dwmright;
            mg.m_Bottom = dwmbottom;
            //判断Vista系统
            if (System.Environment.OSVersion.Version.Major >= 6)
            {
                DwmIsCompositionEnabled(ref flag);    //检测Aero是否为打开
                if (flag > 0)
                {
                    DwmExtendFrameIntoClientArea(this.Handle, ref mg);
                }
                else
                {
                    dwmEnabled = false;
                    dwmleft = 0;
                    dwmtop = 0;
                    dwmright = 0;
                    dwmbottom = 0;
                    //MessageBox.Show("Desktop Composition is Disabled!");
                }
            }
            else
            {
                dwmEnabled = false;
                dwmleft = 0;
                dwmtop = 0;
                dwmright = 0;
                dwmbottom = 0;
                //MessageBox.Show("Please run this on Windows Vista.");
            }
            GC.Collect();
            #endregion
        }
    }
}
